package com.summer.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.summer.common.R;
import com.summer.entity.Employee;
import com.summer.service.EmployeeService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;

@RestController
@RequestMapping("/employee")
@Slf4j
public class EmployeeController {

    @Autowired
    private EmployeeService employeeService;

    /**
     * 员工登录功能
     * @param request   用于设置session属性
     * @param employee  用于接收前端json
     * @return          返回json：R封装的结果
     */
    @PostMapping("/login")
    public R<Employee> employeeLogin(HttpServletRequest request, @RequestBody Employee employee){
        log.info("执行登录请求，登录参数信息为：{}", employee.toString());
        // 1. 前端发送的json数据的password进行md5加密
        String password = employee.getPassword();
        password = DigestUtils.md5DigestAsHex(password.getBytes());

        // 2. 查询数据库，判断username是否存在，若不存在则返回登录失败信息
        LambdaQueryWrapper<Employee> lqw = new LambdaQueryWrapper<>();
        lqw.eq(Employee::getUsername, employee.getUsername());
        // TODO username已设置唯一约束，getOne对应mapper的selectOne方法
        Employee employeeInDataBase = employeeService.getOne(lqw);
        if(employeeInDataBase == null){
            return R.error("用户名不存在！登陆失败");
        }

        // 3. 若username存在则校验密码，密码错误则返回登录失败信息
        if(!employeeInDataBase.getPassword().equals(password)){
           return R.error("密码错误！登录失败");
        }

        // 4. 若密码正确，判断账号状态是否启用，若不启用则返回账号状态禁用信息
        if(employeeInDataBase.getStatus() == 0){
            return R.error("账号已被禁用");
        }

        // 5. 若启用则将用户id存入session，返回登录成功信息
        request.getSession().setAttribute("employee", employeeInDataBase.getId());
        return R.success(employeeInDataBase);
    }

    /**
     * 退出功能
     *
     * @param request 清除session登录数据
     * @return 返回退出成功信息
     */
    @PostMapping("/logout")
    public R<String> employeeLogout(HttpServletRequest request) {

        log.info("执行退出方法...");
        // 1. 将session属性移除
        request.getSession().removeAttribute("employee");
        // 2. 返回登出成功信息
        return R.success("退出成功！");
    }

    /**
     * 添加员工
     * @param request  用于获取session
     * @param employee 用于接收json
     * @return 返回添加成功信息
     */
    @PostMapping
    public R<String> addEmployee(HttpServletRequest request, @RequestBody Employee employee){
        //1. 获取前端发送的json数据，封装员工数据
        // 1.1 给员工设置初始密码并md5加密
        log.info("请求执行添加员工方法，员工信息为：{}", employee.toString());
        employee.setPassword(DigestUtils.md5DigestAsHex("123456".getBytes()));

        // 1.2 设置创建时间与更新时间属性、设置创建人与更新人

        /*    使用MP通用字段自动填充功能：TODO
                1. 在通用字段上加 @TableField(fill = FieldFill.INSERT_UPDATE) 注解。
                    FieldFill.INSERT_UPDATE：新增或更新操作时执行自动填充
                    FieldFill.INSERT：新增操作时执行自动填充

                2. 创建MyMetaObjectHandler类实现接口MetaObjectHandler并实现两个方法（新增时操作和更新时操作）
                    2.1 添加@Component注解
                    2.2 调用形参metaObject.setValue(fieldName, fieldValue)为实体类属性填充值

                3. 创建类用于设置在当前线程存储中添加属性键值对
                    3.1 创建静态常量ThreadLocal对象，可通过其API setAttribute和setAttribute存取自定义数据
                    3.2 创建setter和getter方法用于存取ThreadLocal的属性键值对

                    ThreadLocal作用：某个线程的唯一标志。为此线程提供存储区域进行存取数据
                    当浏览器向服务器发送http请求时，此请求线程经过 Filter -> MyMetaObjectHandler -> SpringMvc的Controller
                    因此可对此请求线程进行存取数据。（这里时是在过滤器存session数据（即用户登录id），在MyMetaObjectHandler取）
        employee.setCreateTime(LocalDateTime.now());
        employee.setUpdateTime(LocalDateTime.now());
        Long id = (Long) request.getSession().getAttribute("employee");
        employee.setCreateUser(id);
        employee.setUpdateUser(id);
        */

        //2. 调用service新增方法添加员工
        employeeService.save(employee);

        //3. 返回添加成功信息
        return R.success("添加成功！");
    }


    /**
     * 分页条件查询controller
     * @param page       当前页
     * @param pageSize   每页显示数
     * @param name       查询条件：员工姓名
     * @return           返回员工信息列表
     */
    @GetMapping("/page")
    public R<Page> getByPageAndCondition(int page, int pageSize, String name){  // 1. 形参接收请求参数

        //2. TODO 调用service层分页查询API获取列表数据

        log.info("执行分页条件查询方法，条件参数为：page:"+page+", pageSize:"+pageSize+", name:"+name);
        Page pageInfo = new Page(page, pageSize);

        LambdaQueryWrapper<Employee> lqw = new LambdaQueryWrapper<>();
        // TODO qw的模糊查询API：like（boolean 条件为true才执行此方法， Employee::get模糊匹配属性, 模糊匹配值）
        lqw.like(StringUtils.isNotEmpty(name), Employee::getName, name);
        // TODO 排序条件
        lqw.orderByDesc(Employee::getUpdateTime);
        employeeService.page(pageInfo, lqw);

        //3. 封装列表数据返回R对象
        return R.success(pageInfo);
    }

    /**
     * 员工信息更新
     * @param request  用于获取session
     * @param employee 用于接收前端json
     * @return         返回修改成功信息
     */
    @PutMapping
    public R<String> setEmployeeState(HttpServletRequest request, @RequestBody Employee employee){ //1. 接收前端json
        log.info("请求修改员工操作，参数信息为：{}", employee.toString());
        //2 对前端的json数据封装修改人和修改时间
        //Long loginId = (Long) request.getSession().getAttribute("employee");
        //employee.setUpdateUser(loginId);
        //employee.setUpdateTime(LocalDateTime.now());

        //3. 调用serviceAPI进行修改操作, TODO updateById 根据id修改, 参数传入实体类即可
        employeeService.updateById(employee);

        //4. 返回修改成功信息
        return R.success("修改成功！");
    }

    /**
     * 根据id查询员工
     * @param id 用于获取请求路径参数id
     * @return   返回单个员工信息并封装为R
     */
    @GetMapping("/{id}")
    public R<Employee> getEmployeeById(@PathVariable Long id){
        log.info("请求根据id查询员工信息：id为 {}", id);
        Employee employee = employeeService.getById(id);
        if(employee == null){
            return R.error("用户不存在");
        }
        return R.success(employee);
    }
}
